package com.tyut.musicdreamer.service.music.service.impl;

import com.tyut.musicdreamer.service.music.service.MusicStorageService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;

/**
 * 存储服务适配器，将通用存储服务适配为音乐存储服务
 */
@Slf4j
@Service
@Primary // 标记为主要Bean
@Order(10) // 设置较高的优先级
@RequiredArgsConstructor
public class StorageServiceAdapter implements MusicStorageService {

    private final ApplicationContext applicationContext;
    private final Environment environment;
    
    private static final String MUSIC_DIRECTORY = "music";
    private static final String COVER_DIRECTORY = "cover";
    
    // 通用存储服务的类名
    private static final String STORAGE_SERVICE_CLASS = "com.tyut.musicdreamer.framework.starter.storage.service.StorageService";
    
    // 上传结果类名
    private static final String UPLOAD_RESULT_CLASS = "com.tyut.musicdreamer.framework.starter.storage.model.UploadResult";
    
    // 存储类别枚举类名
    private static final String STORAGE_CLASS_ENUM = "com.tyut.musicdreamer.framework.starter.storage.model.StorageClass";
    
    @PostConstruct
    public void init() {
        try {
            log.info("======================== 存储服务初始化 ========================");
            log.info("存储服务类型: {}", environment.getProperty("musicdreamer.storage.type"));
            
            // 获取允许的文件类型列表
            try {
                int i = 0;
                while (true) {
                    String allowedType = environment.getProperty("musicdreamer.storage.allowed-types[" + i + "]");
                    if (allowedType == null) break;
                    log.info("允许的文件类型[{}]: {}", i, allowedType);
                    i++;
                }
            } catch (Exception e) {
                log.warn("获取允许的文件类型列表失败", e);
            }
            
            log.info("最大文件大小: {}", environment.getProperty("musicdreamer.storage.max-size"));
            
            Object storageService = getStorageService();
            log.info("实际使用的存储服务实现: {}", storageService.getClass().getName());
            log.info("================================================================");
        } catch (Exception e) {
            log.error("存储服务初始化信息打印失败", e);
        }
    }

    /**
     * 获取存储服务
     */
    public Object getStorageService() {
        try {
            // 获取StorageService类
            Class<?> storageServiceClass = Class.forName(STORAGE_SERVICE_CLASS);
            // 从Spring上下文中获取StorageService实例
            return applicationContext.getBean(storageServiceClass);
        } catch (Exception e) {
            log.error("获取StorageService失败", e);
            throw new RuntimeException("获取StorageService失败，请确保已正确配置存储模块", e);
        }
    }

    @Override
    public String store(MultipartFile file) {
        try {
            log.info("开始存储音乐文件: 文件名={}, 内容类型={}, 大小={}字节", 
                file.getOriginalFilename(), file.getContentType(), file.getSize());
            
            // 检查文件类型
            String contentType = file.getContentType();
            if (contentType != null && contentType.startsWith("audio/")) {
                log.info("检测到音频文件: {}", contentType);
                // 确保音频文件类型正确
                if (contentType.equals("audio/mpeg") || 
                    contentType.equals("audio/mp3") || 
                    file.getOriginalFilename().toLowerCase().endsWith(".mp3")) {
                    // 对于MP3文件，确保内容类型为audio/mpeg
                    log.info("处理MP3音频文件");
                }
            }
            
            Object storageService = getStorageService();
            log.info("使用存储服务: {}", storageService.getClass().getName());
            
            // 调用store方法
            Method method = storageService.getClass().getMethod("store", MultipartFile.class, String.class);
            Object result = method.invoke(storageService, file, MUSIC_DIRECTORY);
            
            // 获取objectKey
            String objectKey = getObjectKey(result);
            log.info("音乐文件存储成功: objectKey={}", objectKey);
            return objectKey;
        } catch (Exception e) {
            log.error("存储音乐文件失败: 文件名={}, 内容类型={}", 
                file.getOriginalFilename(), file.getContentType(), e);
            throw new RuntimeException("存储音乐文件失败", e);
        }
    }

    @Override
    public String storeCover(MultipartFile file) {
        try {
            log.info("开始存储封面文件: 文件名={}, 内容类型={}, 大小={}字节", 
                file.getOriginalFilename(), file.getContentType(), file.getSize());
            
            // 检查文件
            if (file == null || file.isEmpty()) {
                log.error("封面文件为空");
                throw new RuntimeException("封面文件为空");
            }
            
            // 检查文件类型
            String contentType = file.getContentType();
            if (contentType == null) {
                log.warn("封面文件内容类型为空，将尝试根据文件名推断");
                // 尝试从文件名推断内容类型
                String fileName = file.getOriginalFilename();
                if (fileName != null) {
                    if (fileName.toLowerCase().endsWith(".jpg") || fileName.toLowerCase().endsWith(".jpeg")) {
                        contentType = "image/jpeg";
                    } else if (fileName.toLowerCase().endsWith(".png")) {
                        contentType = "image/png";
                    } else if (fileName.toLowerCase().endsWith(".gif")) {
                        contentType = "image/gif";
                    } else {
                        contentType = "application/octet-stream";
                    }
                    log.info("根据文件名推断内容类型: {}", contentType);
                }
            }
            
            // 检查是否为图片类型
            if (contentType != null && !contentType.startsWith("image/")) {
                log.warn("封面文件类型不是图片: {}", contentType);
            }
            
            // 获取存储服务
            Object storageService = getStorageService();
            log.info("使用存储服务: {}", storageService.getClass().getName());
            
            // 检查文件内容是否可读
            try {
                byte[] fileContent = file.getBytes();
                log.info("成功读取封面文件内容，大小: {} 字节", fileContent.length);
            } catch (IOException e) {
                log.error("读取封面文件内容失败", e);
                throw new RuntimeException("读取封面文件内容失败", e);
            }
            
            // 调用store方法
            Method method = storageService.getClass().getMethod("store", MultipartFile.class, String.class);
            Object result = method.invoke(storageService, file, COVER_DIRECTORY);
            
            // 检查结果
            if (result == null) {
                log.error("存储服务返回空结果");
                throw new RuntimeException("存储封面文件失败，存储服务返回空结果");
            }
            
            // 获取objectKey
            String objectKey = getObjectKey(result);
            if (objectKey == null || objectKey.isEmpty()) {
                log.error("存储服务返回的objectKey为空");
                throw new RuntimeException("存储封面文件失败，返回的objectKey为空");
            }
            
            log.info("封面文件存储成功: objectKey={}", objectKey);
            return objectKey;
        } catch (Exception e) {
            log.error("存储封面文件失败: 文件名={}, 内容类型={}", 
                file.getOriginalFilename(), file.getContentType(), e);
            throw new RuntimeException("存储封面文件失败: " + e.getMessage(), e);
        }
    }

    @Override
    public boolean delete(String objectKey) {
        try {
            Object storageService = getStorageService();
            
            // 调用delete方法
            Method method = storageService.getClass().getMethod("delete", String.class);
            return (boolean) method.invoke(storageService, objectKey);
        } catch (Exception e) {
            log.error("删除文件失败", e);
            return false;
        }
    }

    @Override
    public String getFileUrl(String objectKey) {
        try {
            Object storageService = getStorageService();
            
            // 调用getFileUrl方法
            Method method = storageService.getClass().getMethod("getFileUrl", String.class);
            return (String) method.invoke(storageService, objectKey);
        } catch (Exception e) {
            log.error("获取文件URL失败", e);
            return null;
        }
    }

    @Override
    public InputStream getFileInputStream(String objectKey) {
        try {
            Object storageService = getStorageService();
            
            // 调用getFileInputStream方法
            Method method = storageService.getClass().getMethod("getFileInputStream", String.class);
            return (InputStream) method.invoke(storageService, objectKey);
        } catch (Exception e) {
            log.error("获取文件输入流失败", e);
            return null;
        }
    }
    
    /**
     * 生成预签名下载URL
     * @param objectKey 对象键
     * @param expirationMinutes 过期时间（分钟）
     * @return 预签名URL
     */
    public String generatePresignedUrl(String objectKey, int expirationMinutes) {
        try {
            Object storageService = getStorageService();
            
            // 调用generatePresignedUrl方法
            Method method = storageService.getClass().getMethod("generatePresignedUrl", String.class, int.class);
            return (String) method.invoke(storageService, objectKey, expirationMinutes);
        } catch (Exception e) {
            log.error("生成预签名URL失败", e);
            return null;
        }
    }
    
    /**
     * 生成预签名上传URL
     * @param filename 文件名
     * @param contentType 内容类型
     * @param expirationMinutes 过期时间（分钟）
     * @return 上传结果
     */
    public Object generatePresignedUploadUrl(String filename, String contentType, int expirationMinutes) {
        try {
            Object storageService = getStorageService();
            
            // 调用generatePresignedUploadUrl方法
            Method method = storageService.getClass().getMethod("generatePresignedUploadUrl", 
                    String.class, String.class, String.class, int.class);
            return method.invoke(storageService, filename, contentType, MUSIC_DIRECTORY, expirationMinutes);
        } catch (Exception e) {
            log.error("生成预签名上传URL失败", e);
            return null;
        }
    }
    
    /**
     * 从上传结果中获取对象键
     */
    private String getObjectKey(Object uploadResult) throws Exception {
        if (uploadResult == null) {
            return null;
        }
        
        // 获取getObjectKey方法
        Method method = uploadResult.getClass().getMethod("getObjectKey");
        return (String) method.invoke(uploadResult);
    }
    
    /**
     * 从上传结果中获取预签名URL
     */
    public String getPresignedUrl(Object uploadResult) {
        if (uploadResult == null) {
            return null;
        }
        
        try {
            // 获取getPresignedUrl方法
            Method method = uploadResult.getClass().getMethod("getPresignedUrl");
            return (String) method.invoke(uploadResult);
        } catch (Exception e) {
            log.error("获取预签名URL失败", e);
            return null;
        }
    }
    
    /**
     * 更新存储类别
     * @param objectKey 对象键
     * @param storageClassName 存储类别名称 (Standard, IA, Archive, ColdArchive)
     * @return 是否更新成功
     */
    public boolean updateStorageClass(String objectKey, String storageClassName) {
        try {
            Object storageService = getStorageService();
            
            // 获取StorageClass枚举类
            Class<?> storageClassEnum = Class.forName(STORAGE_CLASS_ENUM);
            Object storageClassValue = null;
            
            // 获取对应的枚举值
            for (Object enumConstant : storageClassEnum.getEnumConstants()) {
                String name = enumConstant.toString();
                if (name.equalsIgnoreCase(storageClassName)) {
                    storageClassValue = enumConstant;
                    break;
                }
            }
            
            if (storageClassValue == null) {
                log.error("无效的存储类别名称: {}", storageClassName);
                return false;
            }
            
            // 调用updateStorageClass方法
            Method method = storageService.getClass().getMethod("updateStorageClass", 
                    String.class, storageClassEnum);
            return (boolean) method.invoke(storageService, objectKey, storageClassValue);
        } catch (Exception e) {
            log.error("更新存储类别失败: objectKey={}, storageClassName={}", objectKey, storageClassName, e);
            return false;
        }
    }
    
    /**
     * 为保持与AliyunOssMusicStorageServiceImpl兼容的方法
     */
    public String generatePresignedDownloadUrl(String objectKey, int expirationMinutes) {
        // 确保objectKey不为空
        if (objectKey == null || objectKey.trim().isEmpty()) {
            log.error("无法生成预签名下载URL: objectKey为空");
            return null;
        }
        
        try {
            // 获取存储服务
            Object storageService = getStorageService();
            
            // 调用generatePresignedUrl方法
            Method method = storageService.getClass().getMethod("generatePresignedUrl", String.class, int.class);
            String url = (String) method.invoke(storageService, objectKey, expirationMinutes);
            
            log.info("生成预签名下载URL成功: objectKey={}, 有效期={}分钟", objectKey, expirationMinutes);
            return url;
        } catch (Exception e) {
            log.error("生成预签名下载URL失败: objectKey={}, expirationMinutes={}", objectKey, expirationMinutes, e);
            // 如果预签名URL生成失败，尝试返回普通文件URL
            return getFileUrl(objectKey);
        }
    }

    /**
     * 创建RTMP直播通道
     * 
     * @param channelName 通道名称
     * @param description 通道描述
     * @return 推流URL和播放URL
     */
    public String[] createLiveChannel(String channelName, String description) {
        try {
            Object storageService = getStorageService();
            
            // 调用createLiveChannel方法
            Method method = storageService.getClass().getMethod("createLiveChannel", String.class, String.class);
            return (String[]) method.invoke(storageService, channelName, description);
        } catch (Exception e) {
            log.error("创建RTMP直播通道失败", e);
            return null;
        }
    }
    
    /**
     * 生成RTMP推流URL
     * 
     * @param channelName 通道名称
     * @param expirationMinutes 过期时间(分钟)
     * @return RTMP推流URL
     */
    public String generateRtmpUrl(String channelName, int expirationMinutes) {
        try {
            Object storageService = getStorageService();
            
            // 调用generateRtmpUrl方法
            Method method = storageService.getClass().getMethod("generateRtmpUrl", String.class, int.class);
            return (String) method.invoke(storageService, channelName, expirationMinutes);
        } catch (Exception e) {
            log.error("生成RTMP推流URL失败", e);
            return null;
        }
    }
} 